/**
 * 
 */
package t4j.concurrency;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

class NIOBlocked implements Runnable{
	private final SocketChannel sc;
	
	public NIOBlocked(SocketChannel sc){
		this.sc = sc;
	}

	@Override
	public void run() {
		
		try {
			System.out.println("Waiting for read() in " + this);
			
			sc.read(ByteBuffer.allocate(1));
			
		}catch(ClosedByInterruptException e){
			System.out.println("ClosedByInterruptException");//当在某个信道的 I/O 操作中处于阻塞状态的某个线程被另一个线程中断时，该线程将收到此经过检查的异常。抛出此异常前将关闭该信道，并设置先前处于阻塞状态的线程的中断状态。 


		}catch(AsynchronousCloseException e){
			System.out.println("AsynchronousCloseException");//当在某个信道的 I/O 操作中处于阻塞状态的某个线程被另一个线程关闭了该信道或部分信道时，该信道所接收的经过检查的异常。
		}catch (IOException e) {
			throw new RuntimeException(e);
		}
		
		System.out.println("Exiting NIOBlocked.run() " + this);
	}
	
	
}

public class NIOInterruption {

	public static void main(String[] args) throws Exception {
		ExecutorService exec = Executors.newCachedThreadPool();
		
		ServerSocket server = new ServerSocket(8080);
		
		InetSocketAddress isa = new InetSocketAddress("localhost", 8080);
		
		SocketChannel sc1 = SocketChannel.open(isa);
		
		SocketChannel sc2 = SocketChannel.open(isa);
		
		Future<?> f = exec.submit(new NIOBlocked(sc1));
		
		exec.execute(new NIOBlocked(sc2));
		
		exec.shutdown();
		
		TimeUnit.SECONDS.sleep(1);
		
		f.cancel(true);//ClosedByInterruptException
		
		TimeUnit.SECONDS.sleep(1);
		
		sc2.close();//AsynchronousCloseException
	}
}
